package com.hospital.hl7package.utils;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.hospital.common.core.utils.DateUtil;
import com.hospital.common.core.utils.StrKit;
import com.hospital.hl7package.module.entity.DrugPrescMaster;
import com.hospital.hl7package.module.entity.Hl7MessageLogs;
import com.hospital.hl7package.module.entity.Hl7MessageRequest;
import com.hospital.hl7package.module.service.DrugPrescMasterService;
import com.hospital.hl7package.module.service.Hl7MessageLogsService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author lvyao
 * @description xml文件转为HL7格式
 * @date 2021/4/23
 */
@Slf4j
public class HL7Util {

    /**
     * 将绝对路径的xml文件转为HL7格式
     *
     * @param fileName
     * @return
     * @throws Exception
     */
    public static String getHl7Message(String fileName) throws Exception {
        Map<String, String> map = new HashMap<>();
        //1.创建SAXBuilder对象
        SAXBuilder saxBuilder = new SAXBuilder();
        //2.创建输入流  "D:\\\\7Edit 2.x\\\\samples\\\\xml\\\\10252612_已申请未计费_20211201101754ORM_O01.xml"
        InputStream is;
        try {
            is = new FileInputStream(new File(fileName));
        } catch (Exception e) {
            return null;
        }
        //3.将输入流加载到build中
        Document document = saxBuilder.build(is);
        //4.获取根节点
        Element rootElement = document.getRootElement();
        //5.获取节点名称数组
        List<String> fildsL = new ArrayList<>();
        //6.获取子节点
        List<Element> children = rootElement.getChildren();
        for (Element child : children) {
            List<Element> childrenList = child.getChildren();
            String elementStr;
            for (Element o : childrenList) {
                String oName = o.getName();
                fildsL.add(oName);
                elementStr = oName.equals("MSH") ? oName : oName + "|";
                List<Element> cclist = o.getChildren();
                if (cclist.size() > 0) {
                    String elementStr1 = "";
                    String firstName1 = "";
                    for (Element ob : cclist) {
                        String obName = ob.getName();
                        String[] obspilt = obName.contains(".") ? StrKit.split(obName, ".") : StrKit.split(obName, "_");
                        int obcontentSize = obspilt == null ? 0 : Integer.parseInt(obspilt[obspilt.length - 1]);
                        List<Element> ddlist = ob.getChildren();
                        if (ddlist.size() > 0) {
                            String elementStr2 = "";
                            for (Element oc : ddlist) {
                                String ocName = oc.getName();
                                String[] ocsplit = ocName.contains(".") ? StrKit.split(ocName, ".") : StrKit.split(ocName, "_");
                                int contentSize = ocsplit == null ? 0 : Integer.parseInt(ocsplit[ocsplit.length - 1]);
                                List<Element> eelist = oc.getChildren();
                                if (eelist.size() > 0) {
                                    String elementStr3 = "";
                                    for (Element oe : eelist) {
                                        String oeName = oe.getName();
                                        String[] oeSplit = oeName.contains(".") ? StrKit.split(oeName, ".") : StrKit.split(oeName, "_");
                                        int oeContentSize = oeSplit == null ? 0 : Integer.parseInt(oeSplit[oeSplit.length - 1]);
                                        elementStr3 += oeContentSize == eelist.size() ? oe.getValue() : oe.getValue() + "&";
                                    }
                                    elementStr2 += contentSize == ddlist.size() ? elementStr3 : elementStr3 + "^";
                                } else {

                                    elementStr2 += contentSize == ddlist.size() ? oc.getValue() : oc.getValue() + "^";
                                }
                            }
                            //判断是否循环~
                            if (firstName1.equals(obName)) {
                                elementStr1 = StrKit.sub(elementStr1, 0, elementStr1.length() - 1);
                                elementStr1 += obcontentSize == cclist.size() ? elementStr2 : "~" + elementStr2 + "|";
                            } else {
                                elementStr1 += obcontentSize == cclist.size() ? elementStr2 : elementStr2 + "|";
                            }
                        } else {
                            elementStr1 += ob.getName().equals("MSH.1") || ob.getName().equals("MSH_1") || obcontentSize == cclist.size() ? ob.getValue() : ob.getValue() + "|";
                        }
                        firstName1 = obName;

                    }
                    elementStr += elementStr1;
                } else {
                    elementStr += o.getValue();
                }
                map.put(String.valueOf(childrenList.indexOf(o)), elementStr);
            }
        }
        String hl7message = "";
        for (int i = 0; i < map.size(); i++) {
            String value = map.get(String.valueOf(i));
            hl7message += value + "\r";
        }
        return hl7message;
    }


    /**
     * 根据传转换类型获取发送消息内容
     *
     * @param hl7MessageRequest
     * @return
     * @throws Exception
     */
    public static List<Hl7MessageLogs> getHl7Message(Hl7MessageRequest hl7MessageRequest,
                                                     Hl7MessageLogsService hl7MessageLogsService,
                                                     String logsUrlPart, String serviceUrlPart,
                                                     String prescFunction, DrugPrescMasterService drugPrescMasterService) throws Exception {
        String returnStr;
        List<Hl7MessageLogs> stringList = new ArrayList<>();
        String[] split = hl7MessageRequest.getFilename().split(",");
        String url = null;
        String sendUrl = null;
        String patientId = null;
        Hl7MessageLogs hl7MessageLogs = null;
        String newStr = null;
        for (String str : split) {
            newStr = null;
            if (str.contains(".xml")||!str.contains("-")) {
                returnStr = HL7Util.getHl7Message(str);
                if (returnStr != null) {
                    if (hl7MessageRequest.getType() != null && hl7MessageRequest.getType().equals("1") && returnStr != null) {
                        returnStr = returnStr.replace("|NW|", "|OH|").replace("|SC|", "|IP|");
                    } else if (hl7MessageRequest.getType() != null && hl7MessageRequest.getType().equals("2") && returnStr != null) {
                        returnStr = returnStr.replace("|NW|", "|OC|").replace("|SC|", "|CA|");
                    }else if (hl7MessageRequest.getType() != null && hl7MessageRequest.getType().equals("3") && returnStr != null) {
                        returnStr = returnStr.replace("|NW|", "|DR|").replace("|SC|", "|DC|");
                    }else if (hl7MessageRequest.getType() != null && hl7MessageRequest.getType().equals("4") && returnStr != null) {
                        returnStr = returnStr.replace("|NW|", "|OH|").replace("|SC|", "|CM|");
                    }
                    newStr = returnStr;
                    String substring = returnStr.substring(returnStr.indexOf("PID"), returnStr.indexOf("PV1"));
                    String[] split1 = getAllString(substring, "|");
                    patientId = split1[3].replace("^", "");
                    sendUrl = hl7MessageRequest.getUrl();
//                    url = hl7MessageRequest.getUrl().replace("http://esb.ht-healthcare.com", "http://172.16.1.200:80") + "/";
                    url = hl7MessageRequest.getUrl().replace(serviceUrlPart, logsUrlPart) + "/";
                    if (!str.contains("-")&&str.length()<25){
                        url = url.replace("applyLab",prescFunction);
                    }
                }
            } else {
                String guid = str.split("-")[0];
                String visitNo = str.split("-")[1];
                hl7MessageLogs = hl7MessageLogsService.getById(guid);
                patientId = hl7MessageLogs.getPatientId();
                returnStr = hl7MessageLogs.getMessage() == null ? hl7MessageLogs.getBmessage().toString() == null ? hl7MessageLogs.getCmessage() : hl7MessageLogs.getBmessage().toString() : hl7MessageLogs.getMessage();
                if (newStr == null) {
                    newStr = returnStr.substring(0, returnStr.indexOf("ORC|"));
                }
                if (hl7MessageRequest.getType() != null && hl7MessageRequest.getType().equals("1") && returnStr != null) {
                    newStr = getNewString(hl7MessageLogs.getToApp(), visitNo, returnStr, "|OH|", "|IP|");
                } else if (hl7MessageRequest.getType() != null && hl7MessageRequest.getType().equals("2") && returnStr != null) {
                    newStr = getNewString(hl7MessageLogs.getToApp(), visitNo, returnStr, "|OC|", "|CA|");
                }else if (hl7MessageRequest.getType() != null && hl7MessageRequest.getType().equals("3") && returnStr != null) {
                     newStr = getNewString(hl7MessageLogs.getToApp(), visitNo, returnStr, "|DR|", "|DC|");
                }else if (hl7MessageRequest.getType() != null && hl7MessageRequest.getType().equals("4") && returnStr != null) {
                    newStr = getNewString(hl7MessageLogs.getToApp(), visitNo, returnStr, "|OH|", "|CM|");
                }
                url = hl7MessageLogs.getUrl();
                sendUrl = hl7MessageLogs.getUrl().replace(logsUrlPart, serviceUrlPart);
            }
            if (newStr != null &&newStr.trim().length()>0){
                hl7MessageLogs = new Hl7MessageLogs();
                String newGuid = IdWorker.get32UUID().toUpperCase();
                hl7MessageLogs.setGuid(newGuid);
                String substring = "";
                if (newStr.contains("EVN|")){
                    substring =  newStr.substring(newStr.indexOf("MSH|"), newStr.indexOf("EVN"));
                }else {
                    substring = newStr.substring(newStr.indexOf("MSH|"), newStr.indexOf("PID"));
                }
                String[] split1 = getAllString(substring, "|");
                split1[6] = DateUtil.getAllTime();
                split1[9] = newGuid;
                String join = StringUtils.join(split1, "|");
                newStr = newStr.replace(substring, join);
                hl7MessageLogs.setUrl(url);
                hl7MessageLogs.setSendUrl(sendUrl);
                hl7MessageLogs.setCount(0);
                hl7MessageLogs.setStatus("0");
                hl7MessageLogs.setCreateDate(new Date());
                hl7MessageLogs.setUpdateDate(new Date());
                String[] allString = getAllString(split1[8], "^");
               String event =  allString[0] + "_" + allString[1] ;
                hl7MessageLogs.setEvent(event);
                if (event.equals("OMP_O09")&&newStr.contains("EVN|")){
                    substring  = newStr.substring(newStr.indexOf("EVN|"), newStr.indexOf("PID"));
                    String[] split2 = getAllString(substring, "|");
                    String[] allString1 = getAllString(split2[5], "^");
                    String orc = newStr.substring(newStr.indexOf("ORC|"), newStr.indexOf("RXO"));
                    String[] allString2 = getAllString(orc, "|");
                    String[] allString4 = getAllString(allString2[2], "^");
                    String s = allString1[0];
                    String s1 = allString4[0];
                    DrugPrescMaster operInfo = drugPrescMasterService.getOne(new QueryWrapper<DrugPrescMaster>().
                            apply(" presc_Date = to_Date({0},'yyyy-MM-dd HH24:mi:ss') and presc_no = {1} and rownum = 1",s,s1));
                    String operDate = "";
                    String operName="";
                    if (operInfo == null){
                        operDate = DateUtil.getAllTime();
                        operName = "无法确定";
                    }else {
                        if (hl7MessageRequest.getType() != null && hl7MessageRequest.getType().equals("1") && returnStr != null) {
                            operDate = DateUtil.formatDate(operInfo.getBillingDatetime(),"yyyyMMddHHmmss");
                            operName = operInfo.getBillingBy();
                        } else if (hl7MessageRequest.getType() != null && hl7MessageRequest.getType().equals("4") && returnStr != null){
                            operDate = DateUtil.formatDate(operInfo.getDispensingDatetime(),"yyyyMMddHHmmss");
                            operName = operInfo.getDispensingProvider();
                        }
                    }
                    allString1[0] = operDate;
                    String[] allString3 = getAllString(allString1[15], "&");
                    allString3[1] = operName;
                    String join1 = StringUtils.join(allString3, "&");
                    allString1[15] = join1;
                    String join2 = StringUtils.join(allString1, "^");
                    split2[5] = join2;
                    String join3 = StringUtils.join(split2, "|");

                    newStr = newStr.replace(substring, join3);
                }
                hl7MessageLogs.setFromApp(split1[2].replace("^", ""));
                hl7MessageLogs.setToApp(split1[4].replace("^", ""));
                if ("NLecg".equals(split1[4].replace("^", ""))&&hl7MessageRequest.getType().equals("1")){
                    String[] obrs = newStr.split("OBR");
                    String[] bill = getAllString(obrs[1], "|");
                    bill[25] = "A";
                    String collect = Arrays.stream(bill).collect(Collectors.joining("|"));
                    newStr =  obrs[0]+"OBR"+collect;
                }
                if (newStr.length() > 4000) {
                    hl7MessageLogs.setBmessage(newStr.getBytes("gbk"));
                } else {
                    hl7MessageLogs.setMessage(newStr);
                }
                hl7MessageLogs.setPatientId(patientId);
                if (hl7MessageLogs != null) {
                    stringList.add(hl7MessageLogs);
                }
            }
        }
        return stringList;
    }

    public static String[] getAllString(String target, String replacement) {
        return target.replace(replacement, ",").split(",");
    }

    public static String getNewString(String toApp,String visitNo,String returnStr,String orc1 ,String orc5){
        String newStr = null;
        if (toApp.equals("LisSoftWare")) {
            String target = "|NW|" + visitNo + "^^^|^^^|^^^|SC|";
            String source = orc1 + visitNo + "^^^|^^^|^^^"+orc5;
            returnStr = returnStr.replace(target, source);
        } else {
            returnStr = returnStr.replace("|NW|", orc1).replace("|SC|", orc5);
        }
        String[] split1 = returnStr.split("ORC");
        newStr = split1[0];
        for (String orc : split1) {
            if (orc.contains(orc1)) {
                newStr = newStr + "ORC" + orc;
            }
        }
        return newStr;
    }

    public static void printString(String type, String param, String body, String hl7Message, String describe, String sendUrl) {
        String desc = null;
        switch (describe) {
            case "1":
                desc = "HL7消息推送失败,网页返回状态不是200";
                break;
            case "2":
                desc = "HL7消息推送成功,返回MSA|AA|";
                break;
            case "3":
                desc = "HL7消息推送成功，但厂商返回消息异常";
                break;
            case "4":
                desc = "HL7消息推送过程中出现异常报错";
                break;
            case "5":
                desc = "配置表参数‘HL7_SERVICE_REPLACE’或‘HL7_LOG_REPLACE’未配置请查看！";
                break;
            default:
                desc = "JSON转换或HL7消息转换异常报错";
                break;
        }
        log.info("=======消息类型（1-计费？0-未计费？2-撤销）" + type + "\r\n" +
                "=======描述：" + desc + "\r\n" +
                "=======推送地址：" + sendUrl + "\r\n" +
                "=======入参：" + param + "\r\n" +
                "=======推送地址返回：" + body + "\r\n" +
                "=======生成得HL7消息：" + hl7Message);
    }

}
